import os.path

from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from django.views import View
from django.db.models import Count
from back.models import *
from server.settings import STATICFILES_DIRS, STATIC_URL
import json


# Create your views here.
class Login(View):
    # 登录验证的get接口
    def get(self, request):
        is_login = request.session.get('isLogin')
        if is_login:
            return HttpResponse("OK")
        return HttpResponse("error")

    # 用于登录的post接口
    def post(self, request):
        data = request.POST
        u_name = data.get("username")
        u_pass = data.get("password")
        status = "error"
        error_msg = ""
        # 获取数据库账号密码，进行比对
        db = User.objects.filter(username=u_name, password=u_pass, status=True)
        if db:
            status = 'success'
            # 设置session中的信息
            request.session['isLogin'] = True
        else:
            error_msg = '用户名或密码错误！'
        # 返回的结果
        res_data = {
            "status": status,
            "username": data.get("username"),
            "error_msg": error_msg
        }
        res = JsonResponse(res_data)
        return res


class Logout(View):
    def post(self, request):
        del request.session['isLogin']
        return HttpResponse()


class Menu(View):
    def get(self, request):
        if request.session.get('isLogin'):
            with open(STATICFILES_DIRS[0] + '/menu.json', 'r', encoding='utf8') as f:
                res = f.read()
            return HttpResponse(res)
        return HttpResponse("error")


class UserData(View):
    # 用于搜索的函数
    def search(self, s):
        if s:
            return User.objects.filter(username__contains=s)
        return User.objects.filter()

    def get(self, request):
        page = request.GET.get('page')
        num = request.GET.get('num')
        search = request.GET.get('search', '')
        # 防止用户输入错误的信息
        try:
            page = int(page if page else '1')
            num = int(num if num else '8')
        except ValueError:
            page = -1
            num = -1
        status = 'error'
        error_msg = '当前未登录！'
        data = {}
        total = {}
        if request.session.get('isLogin'):
            if page >= 0 and num >= 0:
                status = 'success'
                error_msg = ''
                search = self.search(search)
                data = search.values('id', 'username', 'mobile',
                                     'email', 'status', 'role_id',
                                     'role__name')[(page - 1) * num:page * num]
                total = search.aggregate(total=Count('pk'))
                page = {"page": page}
            else:
                page = {}
                error_msg = '参数错误！'
        else:
            page = {}
        res_data = {
            "status": status,
            "error_msg": error_msg,
            "data": list(data),
            **total,
            **page
        }
        return JsonResponse(res_data)

    def put(self, request, id, status):
        is_login = request.session.get('isLogin')
        if is_login:
            res = User.objects.filter(pk=id).first()
            if res:
                res.status = status
                res.save()
                return HttpResponse('OK')
        return HttpResponse('error')


class SetUser(View):
    def post(self, request):
        if request.session.get('isLogin'):
            username = request.POST.get('username')
            password = request.POST.get('password')
            email = request.POST.get('email', '')
            mobile = request.POST.get('mobile', '')
            id = request.POST.get('id')
            if username:
                if id:
                    obj = User.objects.filter(pk=int(id)).first()
                else:
                    obj = User()
                obj.username = username
                if not id:
                    obj.password = password
                # 默认角色为角色列表最新添加的一个（即最后一个）
                obj.role = Role.objects.order_by('-pk').first()
                obj.email = email
                obj.mobile = mobile
                obj.save()
                return HttpResponse('OK')
        return HttpResponse('error')


class DelUser(View):
    def post(self, request):
        id = request.POST.get('id')
        if request.session.get('isLogin'):
            User.objects.filter(pk=int(id)).delete()
            return HttpResponse("OK")
        return HttpResponse("error")


class AddRole(View):
    def post(self, request):
        status = 'error'
        data = []
        name = request.POST.get('name')
        direction = request.POST.get('direction', '')
        if request.session.get('isLogin'):
            status = 'success'
            obj = Role.objects.create(name=name, direction=direction)
            data = Roles().get_roles(obj.id)
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class SetRole(View):
    def post(self, request):
        status = 'error'
        data = []
        id = request.POST.get('id')
        name = request.POST.get('name')
        direction = request.POST.get('direction', '')
        if request.session.get('isLogin'):
            status = 'success'
            obj = Role.objects.filter(pk=id).first()
            obj.name = name
            obj.direction = direction
            obj.save()
            data = Roles().get_roles(obj.id)
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class DelRole(View):
    def post(self, request):
        status = 'error'
        data = []
        id = request.POST.get('id')
        if request.session.get('isLogin'):
            status = 'OK'
            Role.objects.filter(pk=id).delete()
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class SetUserRole(View):
    def post(self, request):
        id = request.POST.get('id')
        rid = request.POST.get('rid')
        if request.session.get('isLogin') and id and rid:
            res = User.objects.filter(pk=id).first()
            res.role_id = rid
            res.save()
            return HttpResponse("OK")
        return HttpResponse("error")


class Rights(View):
    # 递归获取规则
    def dfs(self, root=0):
        children = Right.objects.filter(pid=root)
        children_list = []
        for child in children:
            children_list.append(self.dfs(child.id))
        if root == 0:
            return children_list
        else:
            _self = Right.objects.filter(pk=root).first()

        if children_list:
            children_list = {'children': children_list}
        else:
            children_list = {}
        res = {
            'id': _self.id,
            'authName': _self.name,
            'path': _self.path,
            'pid': _self.pid,
            'level': _self.level,
            **children_list
        }
        return res

    def get(self, request, type):
        status = 'error'
        data = []
        if request.session.get('isLogin'):
            if type == 'tree':
                data = self.dfs()
            elif type == 'list':
                data = Right.objects.values()
            status = 'success'
        res = {
            'data': list(data),
            'status': status
        }
        return JsonResponse(res)


class Roles(View):
    def get_roles(self, id=0):
        if id:
            roles = Role.objects.filter(pk=id)
        else:
            roles = Role.objects.all()
        roles_list = []
        for role in roles:
            rights = role.right.values_list('id')
            rights_no_half = role.right.filter(level=3).values_list('id')
            rights = list(map(lambda x: x[0], list(rights)))
            rights_no_half = list(map(lambda x: x[0], list(rights_no_half)))
            res = {
                'id': role.id,
                'name': role.name,
                'direction': role.direction,
                # 包含所有完全选中和半选中的规则
                'rights': rights,
                # 只包含完全选中的规则
                'rights_no_half': rights_no_half
            }
            roles_list.append(res)
        return roles_list

    def get(self, request):
        status = 'error'
        data = []
        if request.session.get('isLogin'):
            data = self.get_roles()
            status = 'success'
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)

    def post(self, request, id):
        status = 'error'
        rights = json.loads(request.body).get('rights', None)
        if request.session.get('isLogin') and rights is not None:
            obj = Role.objects.filter(pk=id).first()
            obj.right.set(rights)
            status = 'OK'
        return HttpResponse(status)

    def put(self, request, id, rid):
        status = 'error'
        data = []
        if request.session.get('isLogin'):
            role = Role.objects.filter(pk=id).first()
            right_list = Right.objects.filter(
                pid_path__regex=r'(^%d,|,%d,|,%d$|^%d$)' % (rid, rid, rid, rid)) \
                .values_list('id')
            right_list = list(map(lambda x: x[0], list(right_list)))
            right_list.append(rid)
            role.right.remove(*right_list)
            # 如果一个根下所有的节点都删完，则将这个根也删除
            # 查询rid的父节点
            pid = Right.objects.filter(pk=rid).first().pid
            # 查询role的right中父id列表包含pid的
            right_list = role.right.filter(
                pid_path__regex=r'(^%d,|,%d,|,%d$|^%d$)' % (pid, pid, pid, pid))
            if not right_list:
                role.right.remove(pid)
            # 新的rights列表
            data = self.get_roles(id)[0]
            status = 'success'
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class Categories(View):
    def dfs(self, root=0):
        children = Category.objects.filter(pid=root)
        children_list = []
        for child in children:
            children_list.append(self.dfs(child.id))
        if root == 0:
            return children_list

        _self = Category.objects.filter(pk=root).first()
        children_list = {'children': children_list}
        res = {
            'id': _self.id,
            'name': _self.name,
            'pid': _self.pid,
            'level': _self.level,
            **children_list
        }
        return res

    def get(self, request):
        status = 'error'
        data = []
        if request.session.get('isLogin'):
            status = 'success'
            data = self.dfs()
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)

    def post(self, request, type):
        status = 'error'
        data = []
        try:
            id = json.loads(request.body).get('id', [])
        except json.JSONDecodeError:
            id = request.POST.get('id')
        name = request.POST.get('name')
        level = request.POST.get('level')
        pid = request.POST.get('pid')
        if request.session.get('isLogin'):
            if type == 'add':
                status = 'success'
                Category.objects.create(name=name, level=level, pid=int(pid))
                data = self.dfs()
            elif type == 'set':
                status = 'success'
                obj = Category.objects.filter(pk=id).first()
                obj.name = name
                obj.save()
                data = self.dfs()
            elif type == 'del':
                status = 'success'
                Category.objects.filter(pk__in=id).delete()
                data = self.dfs()
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class Params(View):
    def get(self, request, type, cid):
        status = 'error'
        data = []
        if request.session.get('isLogin'):
            status = 'success'
            if type == 'all':
                data = {
                    'dynamic': list(Param.objects.filter(category_id=cid, type='dynamic').values()),
                    'static': list(Param.objects.filter(category_id=cid, type='static').values())
                }
            else:
                data = list(Param.objects.filter(category_id=cid, type=type).values())
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)

    def post(self, request, mode):
        status = 'error'
        data = []
        # add参数
        name = request.POST.get('name')
        cid = request.POST.get('cid')
        type = request.POST.get('type')

        # set_values参数
        id = request.POST.get('id')
        values = request.POST.get('values')
        if request.session.get('isLogin'):
            status = 'success'
            if mode == 'add':
                Param.objects.create(name=name, category_id=cid, type=type)
            elif mode == 'set_values':
                Param.objects.filter(pk=id).update(values=values)
                status = 'OK'
            else:
                status = 'error'
            if status == 'success':
                data = list(Param.objects.filter(category_id=cid, type=type).values())
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class Goods(View):
    def get(self, request):
        status = 'error'
        data = {}
        page = int(request.GET.get('page', '1'))
        num = int(request.GET.get('num', '8'))
        search = request.GET.get('search', '')
        total = {}
        if request.session.get('isLogin') and page > 0 and num >= 0:
            status = 'success'
            data = Good.objects.filter(name__contains=search)
            data = data.values('id', 'name', 'price',
                               'params', 'date', 'images',
                               'category_id', 'direction',
                               'category__name').order_by('-date')[(page - 1) * num:page * num]
            total = data.aggregate(total=Count('pk'))
            data = list(data)
        res = {
            'status': status,
            'data': data,
            **total
        }
        return JsonResponse(res)

    def post(self, request, type):
        status = 'error'
        data = {}
        if request.session.get('isLogin'):
            status = 'success'
            if type == 'add':
                status = 'OK'
                body = json.loads(request.body)
                cid = body.pop('cid')
                body['category_id'] = cid
                Good.objects.create(**body)
            elif type == 'del':
                status = 'OK'
                id = request.POST.get('id')
                if id:
                    id = int(id)
                Good.objects.filter(pk=id).delete()
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class Orders(View):
    def get(self, request):
        status = 'error'
        data = {}
        page = int(request.GET.get('page', '1'))
        num = int(request.GET.get('num', '8'))
        search = request.GET.get('search', '')
        total = {}
        if request.session.get('isLogin') and page > 0 and num >= 0:
            status = 'success'
            data = Order.objects.filter(good__name__contains=search)
            data = data.values('id', 'num', 'total_pay', 'is_pay',
                               'express_code', 'address', 'date',
                               'good_id', 'good__price', 'good__name',
                               'good__category__name').order_by('-date')[(page - 1) * num:page * num]
            total = data.aggregate(total=Count('pk'))
            data = list(data)
        res = {
            'status': status,
            'data': data,
            **total
        }
        return JsonResponse(res)

    def post(self, request, type):
        status = 'error'
        data = {}
        if request.session.get('isLogin'):
            status = 'success'
            if type == 'set':
                status = 'OK'
                id = request.POST.get('id')
                address = request.POST.get('address', '')
                express_code = request.POST.get('express_code', '')
                Order.objects.filter(pk=id).update(address=address, express_code=express_code)
            elif type == 'del':
                pass
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class Express(View):
    def get(self, request, express_code):
        status = 'error'
        data = {}
        if request.session.get('isLogin'):
            status = 'success'
            # 这里本来应该发起快递单号查询 但是无法对接接口
            # 只能使用静态文件返回假数据
            with open(STATICFILES_DIRS[0] + '/expressData.json', 'r', encoding='utf8') as f:
                data = json.load(f)
        res = {
            'status': status,
            'express_code': express_code,
            'data': data,
            # 已完成订单的type为1，未完成type=0
            'type': 1
        }
        return JsonResponse(res)


class Upload(View):
    def handle_uploaded_file(self, f, path):
        with open(path, 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)

    def post(self, request, path):
        file = request.FILES.get('file')
        status = 'error'
        data = {}
        if request.session.get('isLogin'):
            status = 'success'
            abs_path = os.path.join(STATICFILES_DIRS[0], path, file.name)
            self.handle_uploaded_file(file, abs_path)
            data = {
                'name': file.name,
                # 之后http:/127.0.0.1:8000需要去掉
                'path': 'http:/127.0.0.1:8000' + os.path.join(STATIC_URL, path, file.name).replace('\\', '/')
            }
        res = {
            'status': status,
            'data': data
        }
        return JsonResponse(res)


class Index(View):
    def get(self, request):
        return render(request, 'index.html')
